/**
 * @file market_order.h
 * @brief 市场订单相关数据结构的定义
 * 
 * @details 该文件定义了交易系统中的核心数据结构，包括市场订单（MarketOrder）、
 * 价格级别（MarketOrdersAtPrice）和最佳买卖盘口（BBO）等。
 * 这些数据结构用于表示和管理限价订单簿中的订单和价格级别。
 * 
 * @author 原作者
 * @date 2023
 */

#pragma once

#include <array>
#include <sstream>
#include "common/types.h"

using namespace Common;

/**
 * @namespace Trading
 * @brief 交易相关的命名空间
 * 
 * @details 包含交易系统的核心组件，如订单、价格级别、订单簿等。
 */
namespace Trading {
  /**
   * @struct MarketOrder
   * @brief 市场订单结构体
   * 
   * @details 由交易引擎使用，用于表示限价订单簿中的单个订单。
   * 存储订单的关键信息，如订单ID、侧向（买/卖）、价格、数量和优先级。
   * 同时作为双向链表中的节点，用于组织同一价格级别上的所有订单，
   * 按照FIFO（先进先出）的顺序排列。
   */
  struct MarketOrder {
    /**
     * @brief 订单ID
     * 
     * @details 唯一标识订单的标识符，用于跟踪和操作订单。
     * 默认值为 OrderId_INVALID，表示无效订单ID。
     */
    OrderId order_id_ = OrderId_INVALID;
    
    /**
     * @brief 订单侧向
     * 
     * @details 订单的交易方向，可以是买入（BUY）或卖出（SELL）。
     * 默认值为 Side::INVALID，表示无效侧向。
     */
    Side side_ = Side::INVALID;
    
    /**
     * @brief 订单价格
     * 
     * @details 订单的价格，用于确定订单在订单簿中的位置和成交条件。
     * 默认值为 Price_INVALID，表示无效价格。
     */
    Price price_ = Price_INVALID;
    
    /**
     * @brief 订单数量
     * 
     * @details 订单的数量，表示要买入或卖出的证券数量。
     * 默认值为 Qty_INVALID，表示无效数量。
     */
    Qty qty_ = Qty_INVALID;
    
    /**
     * @brief 订单优先级
     * 
     * @details 订单的优先级，用于在同一价格级别上确定订单的执行顺序。
     * 默认值为 Priority_INVALID，表示无效优先级。
     */
    Priority priority_ = Priority_INVALID;

    /**
     * @brief 前一个订单指针
     * 
     * @details 指向同一价格级别中的前一个订单的指针，用于实现双向链表。
     * 如果该订单是链表中的第一个订单，则指向链表中的最后一个订单，
     * 形成一个循环双向链表。
     */
    MarketOrder *prev_order_ = nullptr;
    
    /**
     * @brief 后一个订单指针
     * 
     * @details 指向同一价格级别中的后一个订单的指针，用于实现双向链表。
     * 如果该订单是链表中的最后一个订单，则指向链表中的第一个订单，
     * 形成一个循环双向链表。
     */
    MarketOrder *next_order_ = nullptr;

    /**
     * @brief 默认构造函数
     * 
     * @details 仅用于与 MemPool 一起使用，允许内存池分配未初始化的对象。
     */
    MarketOrder() = default;

    /**
     * @brief 构造函数
     * 
     * @details 初始化市场订单对象，设置订单的各个属性和链表指针。
     * 
     * @param order_id 订单ID，唯一标识订单
     * @param side 订单侧向，可以是买入或卖出
     * @param price 订单价格
     * @param qty 订单数量
     * @param priority 订单优先级
     * @param prev_order 前一个订单指针
     * @param next_order 后一个订单指针
     */
    MarketOrder(OrderId order_id, Side side, Price price, Qty qty, Priority priority, MarketOrder *prev_order, MarketOrder *next_order) noexcept
        : order_id_(order_id), side_(side), price_(price), qty_(qty), priority_(priority), prev_order_(prev_order), next_order_(next_order) {}

    /**
     * @brief 将订单转换为字符串表示
     * 
     * @details 生成订单的文本表示，包括订单ID、侧向、价格、数量、优先级
     * 以及前后订单的ID。主要用于调试和日志记录。
     * 
     * @return 订单的字符串表示
     */
    auto toString() const -> std::string;
  };

  /**
   * @typedef OrderHashMap
   * @brief 订单ID到市场订单的映射
   * 
   * @details 使用固定大小的数组实现的哈希表，用于快速根据订单ID查找对应的市场订单对象。
   * 数组大小由 ME_MAX_ORDER_IDS 常量决定，表示系统支持的最大订单数量。
   */
  typedef std::array<MarketOrder *, ME_MAX_ORDER_IDS> OrderHashMap;

  /**
   * @struct MarketOrdersAtPrice
   * @brief 价格级别结构体
   * 
   * @details 由交易引擎使用，用于表示限价订单簿中的一个价格级别。
   * 内部维护了一个按FIFO（先进先出）顺序排列的 MarketOrder 对象列表。
   * 每个价格级别包含侧向（买/卖）、价格和该价格上的所有订单。
   * 同时作为双向链表中的节点，用于组织不同价格级别，按照价格从最激进到最不激进的顺序排列。
   */
  struct MarketOrdersAtPrice {
    /**
     * @brief 价格级别的侧向
     * 
     * @details 价格级别的交易方向，可以是买入（BUY）或卖出（SELL）。
     * 默认值为 Side::INVALID，表示无效侧向。
     */
    Side side_ = Side::INVALID;
    
    /**
     * @brief 价格级别的价格
     * 
     * @details 该价格级别的价格值，用于唯一标识价格级别。
     * 默认值为 Price_INVALID，表示无效价格。
     */
    Price price_ = Price_INVALID;

    /**
     * @brief 第一个市场订单指针
     * 
     * @details 指向该价格级别上的第一个市场订单的指针。
     * 该指针是进入该价格级别上所有订单循环双向链表的入口点。
     */
    MarketOrder *first_mkt_order_ = nullptr;

    /**
     * @brief 前一个价格级别指针
     * 
     * @details 指向前一个价格级别的指针，用于实现价格级别的双向链表。
     * 价格级别按照价格从最激进到最不激进的顺序排列，对于买入侧是价格降序，
     * 对于卖出侧是价格升序。
     */
    MarketOrdersAtPrice *prev_entry_ = nullptr;
    
    /**
     * @brief 后一个价格级别指针
     * 
     * @details 指向后一个价格级别的指针，用于实现价格级别的双向链表。
     * 价格级别按照价格从最激进到最不激进的顺序排列，对于买入侧是价格降序，
     * 对于卖出侧是价格升序。
     */
    MarketOrdersAtPrice *next_entry_ = nullptr;

    /**
     * @brief 默认构造函数
     * 
     * @details 仅用于与 MemPool 一起使用，允许内存池分配未初始化的对象。
     */
    MarketOrdersAtPrice() = default;

    /**
     * @brief 构造函数
     * 
     * @details 初始化价格级别对象，设置侧向、价格、第一个订单指针和链表指针。
     * 
     * @param side 价格级别的侧向，可以是买入或卖出
     * @param price 价格级别的价格
     * @param first_mkt_order 指向该价格级别上第一个订单的指针
     * @param prev_entry 指向前一个价格级别的指针
     * @param next_entry 指向后一个价格级别的指针
     */
    MarketOrdersAtPrice(Side side, Price price, MarketOrder *first_mkt_order, MarketOrdersAtPrice *prev_entry, MarketOrdersAtPrice *next_entry)
        : side_(side), price_(price), first_mkt_order_(first_mkt_order), prev_entry_(prev_entry), next_entry_(next_entry) {}

    /**
     * @brief 将价格级别转换为字符串表示
     * 
     * @details 生成价格级别的文本表示，包括侧向、价格、第一个订单信息
     * 以及前后价格级别的价格。主要用于调试和日志记录。
     * 
     * @return 价格级别的字符串表示
     */
    auto toString() const {
      std::stringstream ss;
      ss << "MarketOrdersAtPrice["
         << "side:" << sideToString(side_) << " "
         << "price:" << priceToString(price_) << " "
         << "first_mkt_order:" << (first_mkt_order_ ? first_mkt_order_->toString() : "null") << " "
         << "prev:" << priceToString(prev_entry_ ? prev_entry_->price_ : Price_INVALID) << " "
         << "next:" << priceToString(next_entry_ ? next_entry_->price_ : Price_INVALID) << "]";

      return ss.str();
    }
  };

  /**
   * @typedef OrdersAtPriceHashMap
   * @brief 价格到价格级别的映射
   * 
   * @details 使用固定大小的数组实现的哈希表，用于快速根据价格查找对应的价格级别对象。
   * 数组大小由 ME_MAX_PRICE_LEVELS 常量决定，表示系统支持的最大价格级别数量。
   */
  typedef std::array<MarketOrdersAtPrice *, ME_MAX_PRICE_LEVELS> OrdersAtPriceHashMap;

  /**
   * @struct BBO
   * @brief 最佳买卖盘口结构体
   * 
   * @details 表示最佳买卖盘口（Best Bid Offer）的抽象，为只需要盘口顶部价格和流动性摘要
   * 而不需要完整订单簿的组件提供信息。存储了当前最佳买入和卖出的价格及数量。
   * 这个结构体可以大大减少需要传递的数据量，特别是在只需要盘口摘要信息的场景下。
   */
  struct BBO {
    /**
     * @brief 最佳买入价格和最佳卖出价格
     * 
     * @details bid_price_ 表示当前订单簿中的最佳买入（出价最高）价格，
     * ask_price_ 表示当前订单簿中的最佳卖出（报价最低）价格。
     * 默认值为 Price_INVALID，表示无效价格。
     */
    Price bid_price_ = Price_INVALID, ask_price_ = Price_INVALID;
    
    /**
     * @brief 最佳买入数量和最佳卖出数量
     * 
     * @details bid_qty_ 表示当前最佳买入价格上的总数量，
     * ask_qty_ 表示当前最佳卖出价格上的总数量。
     * 默认值为 Qty_INVALID，表示无效数量。
     */
    Qty bid_qty_ = Qty_INVALID, ask_qty_ = Qty_INVALID;

    /**
     * @brief 将最佳买卖盘口转换为字符串表示
     * 
     * @details 生成最佳买卖盘口的文本表示，格式为 "BBO{bid_qty@bid_price X ask_price@ask_qty}"。
     * 主要用于调试和日志记录。
     * 
     * @return 最佳买卖盘口的字符串表示
     */
    auto toString() const {
      std::stringstream ss;
      ss << "BBO{"
         << qtyToString(bid_qty_) << "@" << priceToString(bid_price_)
         << "X"
         << priceToString(ask_price_) << "@" << qtyToString(ask_qty_)
         << "}";

      return ss.str();
    };
  };
}
